/*  
    add    累加求和函数
    
        @param  number  num1    累加求和的第一个数值
        @param  number  num2    累加求和的第二个数值

        @return number  res     累加求和的结果

    输入的数据必须可以转化为数值类型 否则 返回值 是 报错信息
    输入得两个数值 大小顺序无所谓 函数会做 大小容错
    函数 通过 for循环 实现 累加求和
    返回值 是 累加求和执行结果

*/

function add( num1 , num2 ){
    // 容错判断 输入数据必须可以转化为数值类型
    num1 = Number( num1 );
    num2 = Number( num2 );

    // 判断数据类型
    if( isNaN( num1 ) ){
        // 如果 数据类型是NaN 返回报错信息
        return '您输入的数据1,格式不符合规范';
    }else if( isNaN( num2 ) ){
        // 如果 数据类型是NaN 返回报错信息
        return '您输入的数据1,格式不符合规范';
    }

    // 判断数值大小
    var min = Math.min( num1 , num2 );
    var max = Math.max( num1 , num2 );

    // 定义变量 存储累加求和结果
    var res = 0 ;

    // 通过 循环实现 累加求和
    for( var i = min ; i <= max ; i++ ){
        res += i ;
    }

    // 通过 return 定义 返回值 
    return res ;
}

/*
   
    isPrimeNumber     质数判断
        @param  number num  需要判断的数值
        @return boolean 是质数返回true 不是质数返回false

*/

function isPrimeNumber( num ){
    // 判断参数是不是数值类型
    num = Number( num );
    if( isNaN( num ) ){
        return '您输入的数值,格式不符合要求';
    }

    // 通过 循环判断 num 是不是 质数
    for( var i = 2 ; i <= num-1 ; i++ ){
        // 如果发生整除 num 就是 合数 不是 质数
        if( num % i === 0 ){
            // 通过 return 返回 false
            // 同时 终止之后循环的执行
            return false ;
        }
    }  
    
    // 如果 循环中 触发整除 执行 return false
    // 这里的 return true 就不会执行
    // 如果 循环中 没有触发整除 证明 num不能整除 是 质数
    // 执行 return true 
    return true ;
}


/*
    isGCD   最大公约数
        @param  number  num1    要求最大公约数的数值1
        @param  number  num2    要求最大公约数的数值2

        @return number  两个数值所求的最大公约数
*/ 
function isGCD( num1 , num2 ){
    // 转化为数值类型 判断 是不是 NaN
    num1 = Number( num1 );
    num2 = Number( num2 );

    if( isNaN( num1 ) ){
        return '您输入的数值1不符合规范';
    }else if( isNaN( num2 ) ){
        return '您输入的数值2不符合规范';
    }

    // 判断数值的大小
    var min = Math.min( num1 , num2 );
    var max = Math.max( num1 , num2 );

    // 求 最大公约数
    if( max % min === 0 ){
        // 如果整除 小 是 最大公约数
        return min ;
    }else{
        // 没有整除 从 小-1 至 1 循环 
        // 第一个同时整除的数值就是最大公约数
        for( var i = min-1 ; i >= 1 ; i-- ){
            if( max % i === 0 && min % i === 0 ){
                return i ;
            }
        }
    }
}

/*
    isLCM   最小公倍
        @param  number  num1 需要判断最小公倍的第一个数值
        @param  number  num2 需要判断最小公倍的第二个数值
        @return number  返回值是最小公倍数

    1,  输入的数据必须是 数值类型
    2,  输入的数据大小顺序任意
*/

function isLCM( num1 , num2 ){
    // 将输入的数据,数据类型转化为数值类型
    num1 = Number( num1 );
    num2 = Number( num2 );

    // 判断 转化结果不能是 NaN
    if( isNaN( num1 ) ){
        return '您输入的num1数据类型不符合要求';
    }else if( isNaN( num2 ) ){
        return '您输入的num2数据类型不符合要求';
    }

    // 获取 较大值 较小值
    var min = Math.min( num1 , num2 );
    var max = Math.max( num1 , num2 );

    // 判断 最小公倍数
    if( max % min === 0 ){
        // 大 可以 整除 小
        // 大 是 最小公倍数
        return max ;

    }else{
        // 不能整除 从 大+1 至  大*小 循环
        for( var i = max+1 ; i <= max*min ; i++ ){
            if( i % max === 0 && i % min === 0 ){
                // 获取第一个可以同时整除的数值
                return i ;
                // 不用再写  break
                // return 就能终止循环还能终止函数的执行
            }
        }
    }
}

/* 
    isEven 判断偶数
        @param  number num  输入的要判断的数值
        @return boolean 判断结果 true是偶数 false 不是偶数

*/

function isEven( num ){
    // 转化为数值类型
    num = Number( num );

    // 不能是NaN
    if( isNaN( num ) ){
        return '您输入的数值,类型不符合要求';
    }

    // 判断 是不是 偶数
    if( num % 2 === 0 ){
        // 可以被2整除 返回值是true 表示是 偶数
        return true;
    }else{
        // 不能被2整除 返回值是false 表示是 奇数
        return false ;
    }
}


/*
    isLeapYear  判断闰年
        @param  number year  输入的要判断的年份
        @return boolean 判断结果 true是闰年 false 是 平年       

*/

function isLeapYear( year ){
    // 转化为数值类型
    year = Number( year );

    // 不能是NaN
    if( isNaN( year ) ){
        return '您输入的数值,类型不符合要求';
    }

    //  判断闰年
    if( ( year % 400 === 0 ) || ( ( year % 4 === 0 ) && ( year % 100 !== 0 ) ) ){
        return true ;
    }else{
        return false ;
    }
}

/*
    isPalindromeString 判断回文字符串
        @param  string  str 需要判断的字符串
        @return boolean 判断结果 true / false

*/

function isPalindromeString( str ){
    // 将 字符串 每一个字符 都转化为数组单元
    var arr = str.split('');
    // 将 数组进行 反转 
    arr.reverse();
    // 将反转的数组 拼接为 新的字符串 没有间隔
    var newStr = arr.join('');
    // 如果 新字符串 等于 原始字符串 
    if( str === newStr ){
        // 返回值是 true 表示 是 回文字符串
        return true;
    }else{
        // 返回值是 false 表示 不是 回文字符串
        return false;
    }
}


/*
    setRGB  随机RGB颜色函数
        @return 返回rgb格式的随机颜色字符串
*/ 

function setRGB(){
    // 模板字符串 解析 3个0-255的随机数
    return `rgb(${ parseInt( Math.random()*256 ) },${ parseInt( Math.random()*256 ) },${ parseInt( Math.random()*256 ) })` ;
}

/*
    setRGBA 随机RGBA颜色函数
        @return 返回rgba格式的随机颜色字符串
*/ 

function setRGBA(){
    // 模板字符串 解析 3个0-255的随机数
    return `rgba(${ parseInt( Math.random()*256 ) },${ parseInt( Math.random()*256 ) },${ parseInt( Math.random()*256 ) },${ parseInt( Math.random()*11 ) / 10 })` ;                              
}


/*
    setVC   随机验证码字符串
        @param  number  num     验证码的位数    默认值是 6
        @param  string  str     验证码的内容    默认值是 小写英文字母 大写英文字母 数字
        @param  boolean bool    验证码内容 能不能重复 默认值是 true 

        @return string  res     拼接生成的验证码字符串

*/

//  封装定义函数 设定参数 同时给参数设定默认值
function setVC( num = 6 , str = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWXYZ0123456789' , bool = true ){
    // 对于输入的数据 做 验证判断

    // 定义一个变量 存储 验证码字符串结果
    var res = '' ;

    // 根据 参数3 的不同数据 执行 不同的拼接操作
    if( bool ){
        //  如果 bool 中 存储 true   验证码内容可以重复
        //  使用for循环 直接循环num次 拼接 num个随机字符
        for( var i = 1 ; i <= num ; i++ ){
            // 生成一个随机索引下标
            var index = parseInt( Math.random()*str.length );

            // 根据随机索引下标 获取一个随机字符 拼接写入验证码字符串
            res += str[index];

        }

    }else{
        //  如果 bool 中 存储 false  验证码内容不能重复
        //  通过 while循环 向 验证码字符串 拼接写入字符 
        //  验证码长度 不足6位 就继续循环 执行 拼接
        while( res.length < num ){
            // 生成一个随机索引下标
            var index = parseInt( Math.random()*str.length );

            // // 获取一个随机的字符
            var vc = str[index];

            // 执行判读 如果 res字符串中 没有随机字符vc 再执行拼接操作
            if( res.indexOf( vc ) === -1 ){
                res += vc ;
            }
        }
    }

    return res

}

/*
    setNewArr1      数组去重1 
        @param  array   arr     需要去重的数组
        @return array   res     去重之后的新的数组
    
    使用 indexOf 方法

*/

function setNewArr1( array ){
    // 创建一个新数组
    var arr = [] ;

    // 循环遍历 原始数组 将 原始数组 写入 新数组
    // 写入时 新数组中没有的数据 再写入
    for( var i = 0 ; i <= array.length-1 ; i++ ){
        if( arr.indexOf( array[i] ) === -1 ){
            arr.push( array[i] );
        }
    }

    // 设定返回值
    return arr ;
}


/*
    setNewArr2      数组去重2 
        @param  array   arr     需要去重的数组
    
    使用 双重for循环方法

*/

function setNewArr2( array ){
    //  对 array 输入的参数数组 进行 双重for循环 
    //  删除重复的数据单元  防止数组坍塌的影响
    for( var i = 0  ; i <= array.length-1-1 ; i++ ){
        for( var j = i+1 ; j <= array.length-1 ; j++ ){
            if( array[i] === array[j] ){
                array.splice( j , 1 );
            }
        }
    }
}


/*
    myGetTime   获取时间数据
        @param  string  t   表示时间字符串
        @return object  返回的存储时间的对象
*/

function myGetTime( t ){
    //  如果 t 存储 数据 按照 t 存储的时间字符串 创建 时间对象
    //  如果 t 存储 undefined   获取当前时间对象   
    if( t === undefined ){
        // 获取 当前时间数据
        var time = new Date();
    }else{
        // 获取 t 中 存储 字符串 对应的时间对象
        var time = new Date( t );
    }

    // 获取年
    var year = time.getFullYear();

    // 获取月份 数值
    var monthNum = time.getMonth() +1 ;

    //前导补零
    // monthNum = monthNum < 10 ? '0' + monthNum : monthNum ; 

    // 获取月份 字符串
    var monthArr = ['一' , '二' , '三' , '四' , '五' , '六' , '七' , '八' , '九' , '十' , '十一' , '十二'] ;
    var monthStr = monthArr[ time.getMonth() ];

    // 获取日期
    var day = time.getDate(); 

    //前导补零
    // day = day < 10 ? '0' + day : day ; 

    // 获取星期
    var weekArr = ['星期日' , '星期一' , '星期二', '星期三', '星期四', '星期五', '星期六' ];
    var weekStr = weekArr[ time.getDay() ] ;
    
    // 获取小时
    var hours = time.getHours();

    //前导补零
    // hours = hours < 10 ? '0' + hours : hours ; 

    // 获取分钟
    var minutes = time.getMinutes();

    //前导补零
    // minutes = minutes < 10 ? '0' + minutes : minutes ; 

    // 获取秒
    var seconds = time.getSeconds();

    //前导补零
    // seconds = seconds < 10 ? '0' + seconds : seconds ; 

    return {
        // 键名 和 变量 是 相同的名称 
        // 对象的简写语法可以就写一个   year
        // year : year,

        year , monthNum , monthStr , day , weekStr , hours , minutes , seconds 
    };
}

/*
    myGetTD     获取时间差
        @param  string  endTime 终止时间
        @return object  返回的存储时间的对象

*/

function myGetTD( endTime ){
    // 创建 结束时间对象 
    // 按照 结束时间字符串 获取结束时间对象
    var end = new Date( endTime );

    // 创建 起始时间对象
    // 也就是 当前时间对象 
    var start = new Date() ;

    // 获取时间差 单位 转化为 秒 
    var time = parseInt( ( end.getTime() - start.getTime() ) / 1000 );

    // 将 时间差转化为 天 小时 分钟 秒
    var days = parseInt( time / (24*60*60) );
    var hours = parseInt( time % (24*60*60) / (60*60) );
    var minutes = parseInt( time % (60*60) / 60 );
    var seconds = time % 60 ;

    // 返回对象
    // 作为函数的返回值 一般不做前导补零 
    // 实际项目需要前导补零 在 js程序中 再去做 前导补零操作
    return { days , hours , minutes , seconds };
}


/*
    获取浏览器地址栏参数数据

        @return object 返回值是 参数键值对对象

*/

function myGetUrlVal(){
    // 创建空对象 准备存储数据结果
    var obj = {} ;

    // 获取浏览器地址栏参数数据 不要第一个字符?问号
    var str = window.location.search.substr( 1 );

    // 以 & 符号为间隔 将字符串 分割为数组
    var arr1 = str.split('&') ;

    // 循环遍历数组 将 数据单元 也就是 键值字符串 以 = 为间隔 分割为数组
    arr1.forEach(function(item){
        // item 就是键值对字符串
        var arr2 = item.split('=');

        // 将 arr2[0] 作为键名 arr2[1] 作为键值 赋值给对象
        // 使用 window.decodeURIComponent() 还原 %十六进制数值 为中文/特殊符号
        obj[ arr2[0] ] = window.decodeURIComponent( arr2[1] );
    })

    // 返回值 就是这个对象
    return obj ;
}